package com.sia.springcloud.service.impl;

import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import com.sia.springcloud.service.IFileParseService;
import com.sia.springcloud.utils.POIUtil;
import com.sia.springcloud.result.ResultUtil;
import freemarker.template.utility.StringUtil;
import lombok.extern.slf4j.Slf4j;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.poifs.filesystem.POIFSFileSystem;
import org.springframework.core.io.ClassPathResource;
import org.springframework.stereotype.Service;
import org.springframework.util.LinkedMultiValueMap;
import org.springframework.util.MultiValueMap;
import org.springframework.web.client.RestTemplate;
import org.springframework.web.multipart.MultipartFile;

import javax.annotation.Resource;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.text.SimpleDateFormat;
import java.util.*;

/**
 * @Author: Sirius
 * @Date: 2022/1/10 16:39
 * @Description: 文件上传下载处理类
 **/
@Slf4j
@Service
public class FileParseService implements IFileParseService {

    @Resource
    private RestTemplate restTemplate;

    @Resource
    private ProtocolService protocolService;


    /**
     * 下载设备和点位批量上传的模板
     *
     * @param protocolName
     * @param type
     */
    @Override
    public void downloadExcelTemplate(HttpServletResponse response, String protocolName, String type) {
        String fileName = protocolName + "_" + type;
        String fullName = "excelTemplate/" + fileName + ".xls";


        ServletOutputStream outputStream = null;
        try {
            ClassPathResource resource = new ClassPathResource(fullName);

            InputStream inputStream = resource.getInputStream();

            POIFSFileSystem poifsFileSystem = new POIFSFileSystem(inputStream);

            //读取excel模板
            HSSFWorkbook hssfWorkbook = new HSSFWorkbook(poifsFileSystem);

            //获取输出流
            outputStream = response.getOutputStream();
            //重置输出流
            response.reset();
            //设定输出文件头
            response.setHeader("Content-disposition", "attachment; filename=" + new String(fileName.getBytes("GB2312"), "8859_1") + ".xls");
            //name属性设置和跨服务器访问有关
            response.setHeader("Access-Control-Allow-Origin", "*");
            //定义输出内容类型
            response.setContentType("text/javascript;charset=UTF-8");

            hssfWorkbook.write(outputStream);
        } catch (IOException e) {
            log.info(e.getMessage());
            log.error("传输excel模板过程中发生异常");
        } finally {
            //关闭流
            try {
                if (outputStream != null) {
                    outputStream.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }


    /**
     * 通过excel批量上传设备信息
     * <p>
     * 这里是不是应该调用protocol-core中的接口？
     *
     * @param request
     * @param excelFile
     * @return
     */
    @Override
    public String uploadDeviceExcel(HttpServletRequest request, MultipartFile excelFile) {
        log.info("上传DeviceExcel~~");
        log.info("文件是否为空：" + excelFile.isEmpty());

        List<MultiValueMap<String, Object>> paramsList = parseAndPackingExcel(request, excelFile);


        if (paramsList == null || paramsList.size() == 0) {
            return ResultUtil.createSimpleFailureJson("excel内容为空");
        }


        //TODO：这里其实应该把请求加入到消息队列里面
        for (int i = 0; i < paramsList.size(); i++) {
            String instanceId = getInstanceIdByProtocolName(request);
            if (instanceId == null) {
                return ResultUtil.createSimpleFailureJson("协议对应的微服务未启动");
            } else {
                String priorityUrl = "http://" + instanceId + "/deviceController/insertDevice";
                MultiValueMap<String, Object> params = paramsList.get(i);
                String result = restTemplate.postForObject(priorityUrl, params, String.class);
                log.info("result:" + result);
            }
        }
        return null;
    }


    /**
     * 通过excel批量上传点位信息
     * <p>
     * 这里是不是应该调用protocol-core中的接口？
     *
     * @param request
     * @param excelFile
     * @return
     */
    //@Override
    public String uploadPointExcel(HttpServletRequest request, MultipartFile excelFile) {
        log.info("上传PointExcel~~");
        log.info("文件是否为空：" + excelFile.isEmpty());

        List<MultiValueMap<String, Object>> paramsList = parseAndPackingExcel(request, excelFile);

        if (paramsList == null || paramsList.size() == 0) {
            return ResultUtil.createSimpleFailureJson("excel内容为空");
        }

        //TODO：这里其实应该把请求加入到消息队列里面
        for (int i = 0; i < paramsList.size(); i++) {
            String instanceId = getInstanceIdByProtocolName(request);
            if (instanceId == null) {
                return ResultUtil.createSimpleFailureJson("协议对应的微服务未启动");
            } else {
                String priorityUrl = "http://" + instanceId + "/pointController/insertPoint";
                MultiValueMap<String, Object> params = paramsList.get(i);
                String result = restTemplate.postForObject(priorityUrl, params, String.class);
                log.info("result:" + result);

            }
        }
        return null;
    }



    /**
     * 根据协议名获取对应的微服务实例路径
     *
     * @param request
     * @return
     */
    private String getInstanceIdByProtocolName(HttpServletRequest request) {
        return protocolService.getInstanceIdByProtocolName(request);
    }


    /**
     * 对request中的参数进行包装
     *
     * @param request
     * @return
     */
    private MultiValueMap<String, Object> packingParams(HttpServletRequest request) {
        // 复制 request 的参数
        Map<String, String[]> parameterMap = request.getParameterMap();
        MultiValueMap<String, Object> params = new LinkedMultiValueMap<String, Object>();
        // 附加参数值
        Set<String> keySet = parameterMap.keySet();
        for (String key : keySet) {
            String[] value = parameterMap.get(key);
            params.add(key, value[0]);
        }
        return params;
    }


    /**
     * 把Excel中的内容包装到一个List中
     *
     * @param request
     * @param excelFile
     * @return
     */
    public List<MultiValueMap<String, Object>> parseAndPackingExcel(HttpServletRequest request, MultipartFile excelFile) {
        List<MultiValueMap<String, Object>> paramsList = new ArrayList<>();

        //如果文件为空，直接返回
        if (null == excelFile || excelFile.isEmpty()) {
            log.info("文件为空");
            return paramsList;
        } else {
            log.info("文件不为空");

        }


        //对上传的文件的名字进行修改
        String originalName = excelFile.getOriginalFilename();
        log.info("originalName:  " + originalName);
        String[] split = originalName.split(".");
        log.info("length:  " + split.length);
        String fileName = originalName.substring(0, originalName.lastIndexOf("."));

        SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd-HH-mm-ss");//设置日期格式
        String date = dateFormat.format(new Date());// new Date()为获取当前系统时间，也可使用当前时间戳

        String name = fileName + (date);

        //检查路径上的文件夹是否存在，如果不存在就新建文件夹
        String path = System.getProperty("user.dir") + "/excelUpload";
        File dir = new File(path);
        if (!dir.exists()) {
            dir.mkdirs();
        }

        //然后用MultipartFile自带的解析方法进行解析
        try {
            //将文件修改名字后上传到指定位置
            excelFile.transferTo(new File(path, name + ".xls"));


            //获取文件
            POIUtil poiUtil = new POIUtil();
            String uploadFileName = System.getProperty("user.dir") + "/excelUpload/" + name + ".xls";


            File uploadfile = new File(uploadFileName);
            log.info("fileName:" + uploadfile);
            log.info("uploadPath:" + uploadfile.getAbsolutePath());
            log.info("fileLength:" + uploadfile.length());

            //对文件进行解析
            //TODO：excel文件解析是不是应该从第三行开始，第一行为英文名，第二行为中文名？
            List<String[]> result = poiUtil.parseExcel(uploadfile);
            log.info("rsult:" + result);

            //包装到一个参数集合的list中，方便直接发起请求
            if (result == null || result.size() <= 1) {
                return paramsList;
            } else {
                String[] paramsName = result.get(0);
                for (int i = 1; i < result.size(); i++) {
                    MultiValueMap<String, Object> params = new LinkedMultiValueMap<String, Object>();
                    String[] paramsValue = result.get(i);
                    for (int j = 0; j < paramsName.length; j++) {

                        // 值为空，就不会添加该参数
                        //为什么采用空字符串相加？
                        if(StringUtils.isNotEmpty(paramsValue[j])){
                            params.add("" + paramsName[j], "" + paramsValue[j]);
                        }
                    }
                    log.info("params:" + params.toString());
                    paramsList.add(params);
                }
            }

        } catch (IOException e) {
            log.info(e.getMessage());
            e.printStackTrace();
            log.error("excel文件上传失败");
        }

        return paramsList;
    }

}
